package com.bardsoftware.foronuvolo.server;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.compass.core.CompassHits;
import org.compass.core.CompassSearchSession;
import org.compass.core.Resource;



import com.bardsoftware.foronuvolo.data.Discussion;
import com.bardsoftware.foronuvolo.data.DatastoreDiscussionChunk;
import com.bardsoftware.foronuvolo.data.DiscussionChunk;
import com.bardsoftware.foronuvolo.data.DiscussionTag;
import com.bardsoftware.foronuvolo.data.ForumUser;
import com.bardsoftware.foronuvolo.data.Message;
import com.bardsoftware.foronuvolo.data.PMF;
import com.bardsoftware.foronuvolo.data.SearchDiscussionChunk;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.repackaged.com.google.common.base.Pair;
import com.google.appengine.repackaged.com.google.common.collect.Maps;

public class SearchServlet extends DiscussionsViewServlet {
    private static MessageCache<String, List<String>> ourSearchCache;

    static {
        Cache cache;
        try {
            cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
        }
        catch (CacheException e) {
            cache = null;
        }
        ourSearchCache = new MessageCache<String, List<String>>(cache, "s");
        ourSearchCache.setVersioned(true);
        MessageCache.addDiscussionCache(ourSearchCache);
    }


    private static final String SEARCH_KEY_WORD_TAGS = "tags:";
    public SearchServlet() {
        super("discussions_view.jsp", Maps.immutableMap("view", null, "namespace", "/search"));
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        if (!req.getRequestURL().toString().startsWith(ForoNuvoloConstants.FORUM_DOMAIN)) {
            return;
        }
        super.doGet(req, resp);
        /*
        RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(JspHelper.getJspName("search.jsp"));
        ForumUser user = com.bardsoftware.foronuvolo.server.UserService.getUser(req);
        req.setAttribute("nickname", user.getNickname());
        if (user != ForumUser.ANONYMOUS) {
            req.setAttribute("user_id", user.getID());
        }
        dispatcher.forward(req, resp);
        */
    }

    @Override
    protected DiscussionChunk getPage(HttpServletRequest req) {
        String query = req.getParameter("q");
        if (query!=null && !"".equals(query)) {
            req.setAttribute("q", query);
            String queryHash = Integer.toString(query.hashCode(), 36);
            List<String> searchResults = ourSearchCache.get(queryHash);
            if (searchResults == null) {
            	if(query.startsWith(SEARCH_KEY_WORD_TAGS)){
            		searchResults = searchByTags(query.substring(SEARCH_KEY_WORD_TAGS.length()));
            	}else{
            		searchResults = search(query);            		
            	}
                ourSearchCache.put(queryHash, searchResults);
            }
            req.setAttribute("content_title", MessageFormat.format("<h1 style='display:inline'>Searching for ''{0}''</h1><span> ({1} results)</span>", query, searchResults.size()));
            String page = req.getParameter("page");
            int startResult = (page == null || "".equals(page)) ? 0 : Integer.parseInt(page);
            return new SearchDiscussionChunk(searchResults, startResult, queryHash);
        }
        return null;
    }

	private List<String> searchByTags(String tagsQuery) {
		List<String> tagNames = new ArrayList<String>();
		for (StringTokenizer tokenizer = new StringTokenizer(tagsQuery, "&");
										tokenizer.hasMoreTokens();) {
			tagNames.add(tokenizer.nextToken());
		}
		List<Discussion> discussions = Discussion.findByTag(tagNames);
		List<String> result = new ArrayList<String>(discussions.size());
		for (Discussion discussion : discussions) {
			result.add(discussion.getID().toString());
		}
		return result;
	}

    private List<String> search(String query) {
        CompassSearchSession searchSession = PMF.getCompass().openSearchSession();

        CompassHits hits = searchSession.find(query);
        List<String> results = new ArrayList<String>(hits.getLength());
        for (int i=0; i<hits.length(); i++) {
            results.add(hits.resource(i).getId());
        }
        return results;
    }



}
